/**
 * @author Tobias Boehm
 *
 * 06.06.2011
 */
package org.anddev.andengine.extension.tbsengine.message.client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.interfaces.PBEKey;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.anddev.andengine.extension.multiplayer.protocol.adt.message.client.ClientMessage;


/**
 * This is a stub for a secure client message which  is doing nothing at the 
 * moment but it will be developed.
 * <p>
 * If you create new message classes you should NOT extend from this class but
 * from {@link AbsClientMessage}.
 * 
 * @author Tobias Boehm
 *
 */
public abstract class SecureClientMessage extends ClientMessage {

	private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    //private static final String ALGORITHM = "AES";
	//private static final byte[] sKeyValue = new byte[] { 'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };
	private static final String PASSWORD = "password";
	
	protected abstract void onReadDecryptedTransmissionData(final DataInputStream pDataInputStream) throws IOException ;
	
	protected abstract void onWriteNonEncryptedTransmissionData(final DataOutputStream pDataOutputStream) throws IOException ;
	
	@Override
	protected void onReadTransmissionData(DataInputStream pDataInputStream)
			throws IOException {
		
		// TODO: resume if I have time
		
		this.onReadDecryptedTransmissionData(pDataInputStream);
		
		/*
		try {
			//final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			final Cipher cipher = Cipher.getInstance(ALGORITHM);
			final Key key = generateKey();
			
			cipher.init(Cipher.DECRYPT_MODE, key);
			// TODO: weiter implementieren		
			
			final CipherInputStream ciperInputStream = new CipherInputStream(pDataInputStream, cipher);
			
			final DataInputStream decryptingDataInputStream = new DataInputStream(ciperInputStream);
			
			this.onReadDecryptedTransmissionData(decryptingDataInputStream);
			
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}

	@Override
	protected void onWriteTransmissionData(DataOutputStream pDataOutputStream)
			throws IOException {
		
		onWriteNonEncryptedTransmissionData(pDataOutputStream);
		
		/*try {
			//final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			final Cipher cipher = Cipher.getInstance(ALGORITHM);
			final Key key = generateKey();
			
			cipher.init(Cipher.ENCRYPT_MODE, key);
			
			// TODO: weiter implementieren		
			
			final CipherOutputStream cipherOutputStream = new CipherOutputStream(pDataOutputStream, cipher);
			
			final DataOutputStream decryptingDataOutputStream = new DataOutputStream(cipherOutputStream);
			
			this.onWriteEncryptedTransmissionData(decryptingDataOutputStream);
			
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}
	
	private static Key generateKey() throws Exception {
      
		// Testcode
		SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");  
		byte[] salt = new byte[16];  
		rand.nextBytes(salt);  
		PBEKeySpec password = new PBEKeySpec(PASSWORD.toCharArray(), salt, 1000, 128);  
		SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHAAND128BITAES-CBC-BC");  
		PBEKey pbeEKey = (PBEKey) factory.generateSecret(password);  
		SecretKey key = new SecretKeySpec(pbeEKey.getEncoded(), "AES"); 
		// Testcode
		
		
		
		//final Key key = new SecretKeySpec(sKeyValue, ALGORITHM);
        // SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        // key = keyFactory.generateSecret(new DESKeySpec(keyValue));
        return key;
    }
}
